using System;
using System.Collections.Specialized;
using DotNetOpenMail;
using DotNetOpenMail.SmtpAuth;

namespace NBox.Service.EmailSender
{
    /// <summary>
    /// Implements the <see cref="EmailProvider"/> using an open source library, 
    /// <see href="http://dotnetopenmail.sourceforge.net/">DotNetOpenMail</see>. 
    /// </summary>
    public class DotNetOpenMailSender : IEmailSender
    {
        private const int DefaultSmtpPort = 25;
        private string _name;
        private string _smtpServer = "localhost";
        private int _port = DefaultSmtpPort;
        private bool _sslEnabled;
        private string _password;
        private string _userName;
        private string _adminEmail;

        /// <summary>
        /// Initializes the specified provider.
        /// </summary>
        /// <param name="name">Friendly Name of the provider.</param>
        /// <param name="configValue">Config value.</param>
        public void Initialize(string name, NameValueCollection configValue)
        {
            _name = name;
            _adminEmail = configValue["adminEmail"];
            _smtpServer = configValue["smtpServer"];
            _password = configValue["password"];
            _userName = configValue["username"];
            if (configValue["port"] != null)
            {
                try
                {
                    _port = int.Parse(configValue["port"]);
                }
                catch (System.FormatException)
                {
                    //Do nothing.
                }
            }
            if (configValue["sslEnabled"] != null)
            {
                try
                {
                    _sslEnabled = bool.Parse(configValue["sslEnabled"]);
                }
                catch (System.FormatException)
                {
                    //Do nothing.
                }
            }
        }

        /// <summary>
        /// Gets or sets the admin email.  This is the email address that 
        /// emails sent to a blog owner appears to be from.  It represents 
        /// the system and might not be a real address.
        /// </summary>
        /// <value></value>
        public string AdminEmail
        {
            get
            {
                return _adminEmail;
            }
            set
            {
                _adminEmail = value;
            }
        }

        /// <summary>
        /// Gets or sets the SMTP server.  If not specified, 
        /// defaults to "localhost";
        /// </summary>
        /// <value></value>
        public string SmtpServer
        {
            get
            {
                if (_smtpServer == null || _smtpServer.Length == 0)
                {
                    _smtpServer = "localhost";
                }
                return _smtpServer;
            }
            set
            {
                _smtpServer = value;
            }
        }

        /// <summary>
        /// Gets and sets the port.
        /// </summary>
        /// <value>The port.</value>
        public int Port
        {
            get { return this._port; }
            set { this._port = value; }
        }

        /// <summary>
        /// Gets and sets the SSL protocol enable.
        /// </summary>
        /// <value>true or false.</value>
        public bool SslEnabled
        {
            get { return this._sslEnabled; }
            set { this._sslEnabled = value; }
        }

        /// <summary>
        /// Gets or sets the password used for SMTP servers that 
        /// require authentication.
        /// </summary>
        /// <value></value>
        public string Password
        {
            get
            {
                return _password;
            }
            set
            {
                _password = value;
            }
        }

        /// <summary>
        /// Gets or sets the name of the user for smpt servers that require authentication.
        /// </summary>
        /// <value></value>
        public string UserName
        {
            get
            {
                return _userName;
            }
            set
            {
                _userName = value;
            }
        }

        /// <summary>
        /// Returns the friendly name of the provider when the provider is initialized.
        /// </summary>
        /// <value></value>
        public string Name
        {
            get
            {
                return _name;
            }
        }

        /// <summary>
        /// Sends an email with the specified parameters.
        /// </summary>
        /// <param name="to">Email address of the recipient.</param>
        /// <param name="from">Email address of the sender.</param>
        /// <param name="subject">Subject of the email.</param>
        /// <param name="message">The body of the email Message.</param>
        /// <returns></returns>
        public void Send(string from, string to, string subject, string message)
        {
            EmailMessage email = new EmailMessage();
            email.FromAddress = new EmailAddress(from);
            email.AddToAddress(new EmailAddress(to));
            email.Subject = subject;
            email.BodyText = message;

            Send(email);
        }

        public void Send(Message message)
        {
            EmailMessage email = new EmailMessage();
            email.FromAddress = new EmailAddress(message.From);
            email.AddToAddress(new EmailAddress(message.To));
            email.Subject = message.Subject;
            email.BodyText = message.Body;

            Send(email);
        }

        private void Send(EmailMessage email)
        {
            SmtpServer smtpServer = new SmtpServer(SmtpServer, Port);

            //Authentication.
            if (this.UserName != null && this.Password != null)
            {
                smtpServer.SmtpAuthToken = new SmtpAuthToken(UserName, Password);
            }

            try
            {
                email.Send(smtpServer);
            }
            //Mail Exception is thrown when there are network or connection errors
            catch (MailException mailEx)
            {
                string msg = String.Format("Connection or network error sending email from {0} to {1}", email.FromAddress, email.ToAddresses);
                //Log.Error(msg, mailEx);
            }
            //SmtpException is thrown for all SMTP exceptions
            catch (SmtpException smtpEx)
            {
                string msg = String.Format("Error sending email from {0} to {1}", email.FromAddress, email.ToAddresses);
                //Log.Error(msg, smtpEx);
            }
        }

        public void Send(Message[] messages)
        {
            foreach (Message message in messages)
            {
                Send(message);
            }
        }
    }
}
